package img

import (
	"fmt"
	"github.com/gabriel-vasile/mimetype"
	"golang.org/x/image/webp"
	"image/png"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

func (im *Img) DownloadImage(override bool) (err error) {
	req, err := http.NewRequest("GET", im.Link, nil)
	if err != nil {
		im.Logger.Fatal(err)
	}

	// Некоторые сайты выкидывают ошибку 403 и недают качать файл, им нужен юзер агент
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0")

	resp, err := http.Get(im.Link)
	if err != nil {
		err = fmt.Errorf("[DownloadImage]> Ошибка при скачивании файла:\n%v\n", err)
	}
	defer resp.Body.Close()

	bytes, err := io.ReadAll(resp.Body)
	if err != nil {
		err = fmt.Errorf("[DownloadImage]> Не удалось считать файл:\n%v\n", err)
		return
	}

	resp, err = http.Get(im.Link)
	if err != nil {
		err = fmt.Errorf("[DownloadImage]> Ошибка при скачивании файла:\n%v\n", err)
	}
	defer resp.Body.Close()

	mimeType := strings.Split(http.DetectContentType(bytes), "/")
	im.Logger.Printf("[DownloadImage]> Тип полученного файла:%v\n", mimeType)

	if mimeType[0] == "image" && mimeType[1] != "webp" {
		(*im).Extension = mimeType[1]
		(*im).FullPath += "." + im.Extension
	} else if mimeType[1] == "webp" {
		im.Logger.Println("[DownloadImage]> Файл типа 'webp' будет сконвертирован в 'png'")
		(*im).Extension = "png"
		(*im).FullPath += "." + im.Extension
	} else {
		err = fmt.Errorf("[DownloadImage]> Полученный файл не является изображением: %v\n", mimeType)
		im.Logger.Print(err)
		return
	}

	err = im.saveImage(override, resp.Body)

	return
}

func (im *Img) LocalCopyImage(override bool) (err error) {
	if _, err = os.Stat(im.Link); err != nil {
		err = fmt.Errorf("[LocalCopyImage]> Не удалось открыть '%s':\n%v\n", im.Link, err)
		im.Logger.Print(err)
		return
	}

	in, err := os.Open(im.Link)
	if err != nil {
		im.Logger.Printf("[LocalSaveImage]> Не удалось открыть файл:\n%v\n", err)
		return
	}

	mtype, err := mimetype.DetectFile(im.Link)
	if err != nil {
		err = fmt.Errorf("[LocalSaveImage]> Не удалось определить тип файла:\n%v\n", err)
		im.Logger.Print(err)
		return
	}
	mimeType := strings.Split(mtype.String(), "/")[0]
	fileType := strings.Split(mtype.String(), "/")[1]

	if mimeType == "image" && fileType != "webp" {
		(*im).Extension = fileType
		(*im).FullPath += "." + im.Extension
	} else if fileType == "webp" {
		im.Logger.Println("[LocalSaveImage]> Файл типа 'webp' будет сконвертирован в 'png'")
		(*im).Extension = "png"
		(*im).FullPath += "." + im.Extension
	} else {
		err = fmt.Errorf("[LocalSaveImage]> Полученный файл не является изображением: %v\n", mimeType)
		im.Logger.Print(err)
		return
	}

	err = im.saveImage(override, in)

	return
}

func (im *Img) saveImage(override bool, meReader io.Reader) (err error) {
	currDir := filepath.Dir(im.FullPath)
	if _, err = os.Stat(im.FullPath); err == nil && !override {
		err = fmt.Errorf("Файл '%s' в папке '%s' существует. Программе не указано разрешение перезаписывать существующие файлы\n", filepath.Base(im.FullPath), currDir)
		im.Logger.Print(err)
		return

	}

	if currDir != "" && currDir != "." && currDir != "."+string(os.PathSeparator) {
		err = os.MkdirAll(currDir, 0754)
		if err != nil {
			err = fmt.Errorf("[saveimage]> Ошибка при создании папки '%s':\n%v", currDir, err)
			return
		}
	}

	out, err := os.Create(im.FullPath)
	if err != nil {
		err = fmt.Errorf("[saveimage]> Ошибка при создании файла:\n%v\n", err)
		return
	} else {
		im.Logger.Println("[saveimage]> Файл создан")
	}

	_, err = io.Copy(out, meReader)
	if err != nil {
		err = fmt.Errorf("[saveimage]> Ошибка при сохранении файла на диск:\n%v\n", err)
		return
	} else {
		im.Logger.Println("[saveimage]> Файл сохранён на диск")
	}
	out.Close()

	mtype, err := mimetype.DetectFile(im.FullPath)
	if err != nil {
		err = fmt.Errorf("Не удалось определить MIME файла: %v\n", mtype.String())
		im.Logger.Print(err)
		return
	}
	fileType := mtype.Extension()[1:]

	if fileType == "webp" {
		out, err = os.OpenFile(im.FullPath, os.O_RDONLY, 0666)

		if err != nil {
			im.Logger.Fatalf("[saveimage]> Не удалось открыть картинку на чтение:\n%v\n", err)
		}

		data, err := webp.Decode(out)
		if err != nil {
			im.Logger.Fatalf("[saveimage]> Не удалось декодировать картинку:\n%v\n", err)
		}
		out.Close()

		out, err = os.OpenFile(im.FullPath, os.O_WRONLY, 0666)
		if err != nil {
			im.Logger.Fatalf("[saveimage]> Не удалось открыть картинку на запись:\n%v\n", err)
		}
		defer out.Close()

		err = png.Encode(out, data)
		if err != nil {
			im.Logger.Fatalf("[saveimage]> Не удалось конвертировать картинку:\n%v\n", err)
		}
	} else if err != nil {
		im.Logger.Print(err)
		return err
	}

	return
}
